# This is a sample Python script.

# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
import re
import csv
import sys
import tkinter as tk
from tkinter import ttk
import threading
import os
from tkinter import filedialog, messagebox


class App:
    def __init__(self, master):
        self.t: threading.Thread = None
        self.master = master
        top_frame = tk.Frame(self.master)
        top_frame.pack(side=tk.TOP, anchor=tk.N, padx=15, pady=15, fill="both")
        settings_frame = tk.LabelFrame(top_frame, text="参数配置", padx=5, pady=5)
        settings_frame.pack(anchor=tk.W, fill="y")
        field_frame_input = tk.Frame(settings_frame)
        field_frame_input.pack(side=tk.TOP, expand=tk.YES, pady=10)
        tk.Label(field_frame_input, text="解析文件路径：").pack(side=tk.LEFT)
        self.var_input_path = tk.StringVar()
        self.input_path = tk.Entry(field_frame_input, textvariable=self.var_input_path, width=60)
        self.input_path.pack(side=tk.LEFT)
        browse_file_btn = tk.Button(field_frame_input, text="选择", command=self.browse_file)
        browse_file_btn.pack(side=tk.RIGHT)
        field_frame_output = tk.Frame(settings_frame)
        field_frame_output.pack(side=tk.TOP, expand=tk.YES, pady=10)
        self.var_output_path = tk.StringVar()
        tk.Label(field_frame_output, text="输出文件路径：", ).pack(side=tk.LEFT)
        self.out_path = tk.Entry(field_frame_output,textvariable=self.var_output_path, width=80)
        self.out_path.pack(side=tk.LEFT)

        field_frame_prefix = tk.Frame(settings_frame)
        field_frame_prefix.pack(side=tk.TOP, expand=tk.YES, pady=10)

        tk.Label(field_frame_prefix, text="行首前缀剔除：").pack(side=tk.LEFT)
        self.iv_prefix_default = tk.IntVar()

        tk.Radiobutton(field_frame_prefix, text="是", padx=10, value=1, variable=self.iv_prefix_default,
                       command=self.click_prefix) \
            .pack(side=tk.LEFT)
        tk.Radiobutton(field_frame_prefix, text="否", padx=10, value=2, variable=self.iv_prefix_default,
                       command=self.click_prefix) \
            .pack(side=tk.LEFT)
        self.iv_prefix_default.set(2)
        self.iv_prefix_word = tk.StringVar()
        self.prefix = tk.Entry(field_frame_prefix, width=60, textvariable=self.iv_prefix_word, state=tk.DISABLED)
        self.prefix.pack(side=tk.LEFT)

        field_frame_command = tk.Frame(settings_frame)
        field_frame_command.pack(side=tk.TOP, expand=tk.YES, pady=10)

        tk.Label(field_frame_command, text="执行命令类型：").pack(side=tk.LEFT)
        self.var_commands = tk.StringVar()
        self.used_commands = ttk.Combobox(field_frame_command, textvariable=self.var_commands, width=90)
        self.used_commands.config(values=['show vlan summary', 'show running-config interface', 'show onu running config'])

        self.used_commands.pack(side=tk.LEFT, expand=tk.YES)
        self.used_commands.current(0)

        # 按钮栏
        action_frame = tk.Frame(top_frame)
        action_frame.pack(side=tk.TOP)
        self.var_info = tk.StringVar()
        self.info_label = tk.Label(action_frame, textvariable=self.var_info)
        self.info_label.config(fg='#f24444')
        self.info_label.pack(side=tk.LEFT, anchor=tk.W)
        self.var_info.set("")
        self.cancel_btn = tk.Button(top_frame, text="取消", width=10)
        self.cancel_btn.pack(side=tk.RIGHT, padx=10, pady=10)
        self.exec_btn = tk.Button(top_frame, text="执行", width=10, command=self.start_task)
        self.exec_btn.pack(side=tk.RIGHT, padx=10, pady=10)

    def start_task(self):
        if self.check_input_var():
            if os.path.exists(self.out_path.get()):
                response = messagebox.askyesno("Confirm", "文件已存在，是否覆盖？")
                if not response:
                    return
            self.t = threading.Thread(target=self.analysis)
            self.t.start()

    def browse_file(self):
        path = filedialog.askopenfilename(title="选择文件", filetypes=(('文本文件', '*.txt'), ('所有文件', '*.*')))
        self.var_input_path.set(path)
        os.path.splitext(path)
        self.var_output_path.set(os.path.splitext(path)[0]+'.csv')
        self.var_info.set("")

    def click_prefix(self):
        if self.iv_prefix_default.get() == 1:
            self.prefix.config(state=tk.NORMAL)
        else:
            self.prefix.config(state=tk.DISABLED)

    def check_input_var(self):
        infile = self.input_path.get()
        outfile = self.out_path.get()
        command = self.used_commands.get()
        is_prefix = self.iv_prefix_default.get()
        prefix_word = self.prefix.get()

        checked = True
        if not infile:
            self.var_info.set("解析文件不能为空！")
            checked = False
        elif not outfile:
            self.var_info.set("输出文件不能为空！")
            checked = False
        elif not command:
            self.var_info.set("命令不能为空！")
            checked = False
        elif is_prefix == 1 and not prefix_word:
            self.var_info.set("行首前缀截取词不能为空！")
            checked = False
        if checked and not os.path.exists(infile):
            self.var_info.set("解析文件不存在！！")
            checked = False

        return checked

    def analysis(self):
        self.exec_btn.config(state=tk.DISABLED)
        infile = self.var_input_path.get()
        outfile = self.var_output_path.get()
        command = self.var_commands.get()
        is_prefix = self.iv_prefix_default.get()
        prefix_word = self.iv_prefix_word.get()
        print(infile, '|', outfile, '|', command, '|', is_prefix, '|', prefix_word)
        result = []
        head = []
        # 分析方法
        with open(infile, "r", encoding="utf-8") as f:
            content = f.read()
            match command:
                case 'show vlan summary':
                    result, head = self.show_vlan_summary(self, content)
                case 'show running-config interface':
                    result, head = self.show_running_config_interface(self, content)
                case 'show onu running config':
                    result, head = self.show_onu_running_config(self, content)

            f.close()

            if len(result) == 0:
                messagebox.showinfo('Warning', '根据匹配规则未解析出数据！')
            else:
                self.write_csv(outfile=outfile, head=head, data=result)
                self.var_info.set("文件解析完成！")

        self.exec_btn.config(state=tk.NORMAL)

    @staticmethod
    def show_vlan_summary(self, content):
        print("start analysis show vlan summary.")
        # 匹配段落
        pattern = r'following:(.+?)#'
        match_list = re.findall(pattern, content, flags=re.DOTALL)
        result = []
        for line in match_list:
            # print(line)
            # 获取字段
            columns = re.split(r"\s{7}", line)

            result.append(list(reversed(columns)))
        return result, ["设备名", "vlan值"]

    @staticmethod
    def show_running_config_interface(self, content):
        # 匹配段落
        print("start analysis show running-config interface.")
        graph_pattern = r'](.+?)#show running-config interface (.+?)\s(.+?)!'
        column_pattern = r'service-port (\d+) vport (.+?) user-vlan (.+?) vlan (.\d+)(.+)'
        match_list = re.findall(graph_pattern, content, flags=re.DOTALL)
        result = []
        for line in match_list:
            if len(line) >= 3:
                values = re.findall(column_pattern, line[2])
                for v in values:
                    column = [line[0], line[1].split('_')[1], v[0], v[3]]
                    svlan = re.findall(r'\d+', v[4])
                    if svlan:
                        column.append(svlan[0])
                    else:
                        column.append("")
                    print(column)
                    result.append(column)
        return result, ["设备名", "gpon-onu", "service port", "vlan", "svlan"]

    @staticmethod
    def show_onu_running_config(self, content):
        # 匹配段落
        # pattern = r'following:(.+?)#'
        # match_list = re.findall(pattern, content, flags=re.DOTALL)
        # result = []
        # for line in match_list:
        #     # 获取字段
        #     columns = re.split(r"\s{7}", line)
        #
        #     result.append(list(reversed(columns)))
        # return result
        return [], []

    def write_csv(self, outfile, head, data):
        try:
            with open(outfile, "w", newline="") as csv_file:
                writer = csv.writer(csv_file)
                writer.writerow(head)
                writer.writerows(data)
                csv_file.close()
        except Exception as e:
            self.var_info.set(sys.exc_info())

    def cancel_task(self):
        print("cancel task.")
root = tk.Tk()
root.geometry('600x500+500+200')
root.title("iText Tool  v1.0")
app = App(root)
root.mainloop()
